package br.com.edumobi.dados;

import org.json.JSONObject;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Date;
import java.util.List;
import br.com.edumobi.P;
import br.com.edumobi.T;
import br.com.edumobi.dados.modelos.Aluno;
import br.com.edumobi.dados.modelos.Cidade;
import br.com.edumobi.dados.modelos.Classificacao;
import br.com.edumobi.dados.modelos.Endereco;
import br.com.edumobi.dados.modelos.Questao;
import br.com.edumobi.dados.modelos.Simulado;
import br.com.edumobi.dados.modelos.enuns.Sexo;
import br.com.edumobi.dados.modelos.enuns.UF;
import br.com.edumobi.excecoes.ExcecaoAtualizacaoDadosAlunoMalsucedida;
import br.com.edumobi.excecoes.ExcecaoAutenticacaoMalsucedida;
import br.com.edumobi.excecoes.ExcecaoCadastroAlunoMalsucedido;
import br.com.edumobi.excecoes.ExcecaoConsultaMalsucedida;
import br.com.edumobi.excecoes.ExcecaoRegerarSenhaAlunoMalsucedido;
import br.com.edumobi.utils.Dates;

public class DadosNuvem implements IDadosNuvem {

    private static final String SERVER = "192.168.0.180:8088";

    private InputStream readJSON(String url) throws IOException, RuntimeException {
        HttpURLConnection conexao = (HttpURLConnection) new URL(url).openConnection();

        conexao.setReadTimeout(10 * 1000);
        conexao.setConnectTimeout(10 * 1000);
        conexao.setDoInput(true);
        conexao.setRequestMethod("GET");

        conexao.connect();

        if (conexao.getResponseCode() == HttpURLConnection.HTTP_OK){
            return conexao.getInputStream();
        } else {
            return null;
        }
    }

    private String inputStreamToString(InputStream inputStream) throws IOException {
        if (inputStream != null) {
            byte[] buffer = new byte[1024];
            int bytesLidos;
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            while ((bytesLidos = inputStream.read(buffer)) > -1){
                byteArrayOutputStream.write(buffer, 0, bytesLidos);
            }
            return new String(byteArrayOutputStream.toByteArray());
        } else {
            return null;
        }
    }

    @Override
    public Aluno autenticarAluno(String email, String senha) throws ExcecaoAutenticacaoMalsucedida {
        if (P.TEST && email.equals(T.MOCK_USUARIO_VALIDO_EMAIL) && senha.equals(T.MOCK_USUARIO_VALIDO_SENHA)) {
            return T.getMockAlunoValido();
        }

        StringBuilder url = new StringBuilder()
                .append("http://")
                .append(SERVER)
                .append("/edumobi/services/validarLogin.do?email=")
                .append(email)
                .append("&senha=")
                .append(senha);

        try {
            String retorno = inputStreamToString(readJSON(url.toString()));

            if (retorno == null || retorno.isEmpty()) {
                throw new ExcecaoAutenticacaoMalsucedida();
            } else {
                JSONObject jsonAluno = new JSONObject(retorno);

                Aluno aluno;

                Long id = jsonAluno.getLong("id");
                String nome = jsonAluno.getString("nome");
                String cpf = jsonAluno.getString("cpf");
                String matricula = jsonAluno.getString("matricula");
                Sexo sexo = Sexo.getEnum(jsonAluno.getString("sexo"));
                Date dataNascimento = Dates.stringParaDate(jsonAluno.getString("dataNascimento"), Dates.FORMATO_YYYY_MM_DD);

                String logradouro = jsonAluno.getString("logradouro");
                String numero = jsonAluno.getString("numero");
                String complemento = jsonAluno.getString("complemento");
                String bairro = jsonAluno.getString("bairro");
                String cep = jsonAluno.getString("cep");

                Cidade cidade = null;

                if (!jsonAluno.isNull("municipio")) {
                    JSONObject jsonCidade = jsonAluno.getJSONObject("municipio");

                    cidade = new Cidade(
                            jsonCidade.getLong("id"),
                            jsonCidade.getString("nome"),
                            UF.getEnum(jsonCidade.getJSONObject("uf").getInt("id")));
                }

                Endereco endereco = new Endereco(logradouro, numero, complemento, bairro, cep, cidade);

                String telefoneResidencial = jsonAluno.getString("telefoneResidencial");
                String telefoneCelular = jsonAluno.getString("celular");

                aluno = new Aluno(
                        id,
                        nome,
                        cpf,
                        email,
                        senha,
                        sexo,
                        matricula,
                        dataNascimento,
                        endereco,
                        telefoneResidencial,
                        telefoneCelular);

                return aluno;
            }
        } catch (Exception excecao) {
            throw new ExcecaoAutenticacaoMalsucedida();
        }
    }

    @Override
    public void cadastrarAluno(String nome, String email, String cpf) throws ExcecaoCadastroAlunoMalsucedido {
        StringBuilder url = new StringBuilder()
                .append("http://")
                .append(SERVER)
                .append("/edumobi/services/");

        try {
            String retorno = inputStreamToString(readJSON(url.toString()));

            if (retorno == null || retorno.isEmpty()) {
                throw new ExcecaoCadastroAlunoMalsucedido();
            }

        } catch (Exception excecao) {
            throw new ExcecaoCadastroAlunoMalsucedido();
        }
    }

    @Override
    public void regerarSenhaAluno(String email) throws ExcecaoRegerarSenhaAlunoMalsucedido {
        StringBuilder url = new StringBuilder()
              .append("http://")
              .append(SERVER)
              .append("/edumobi/services/regerarSenha.do?email=")
              .append(email);

        try {
            String retorno = inputStreamToString(readJSON(url.toString()));

            if (retorno == null || retorno.isEmpty()) {
                throw new ExcecaoAutenticacaoMalsucedida();
            }

        } catch (Exception excecao) {
            throw new ExcecaoRegerarSenhaAlunoMalsucedido();
        }
    }

    @Override
    public void salvarDadosAluno(Aluno aluno) throws ExcecaoAtualizacaoDadosAlunoMalsucedida {
        StringBuilder url = new StringBuilder()
                .append("http://")
                .append(SERVER)
                .append("/edumobi/services/");

        try {
            String retorno = inputStreamToString(readJSON(url.toString()));

            if (retorno == null || retorno.isEmpty()) {
                throw new ExcecaoCadastroAlunoMalsucedido();
            }

        } catch (Exception excecao) {
            throw new ExcecaoAtualizacaoDadosAlunoMalsucedida();
        }
    }

    @Override
    public List<Classificacao> consultarClassificacoes(Date dataDeAtualizacao) throws ExcecaoConsultaMalsucedida {
        if (P.TEST) {
            return T.getMockListaDeClassificacoes();
        }

        StringBuilder url = new StringBuilder()
                .append("http://")
                .append(SERVER)
                .append("/edumobi/services/");

        try {
            String retorno = inputStreamToString(readJSON(url.toString()));

            if (retorno == null || retorno.isEmpty()) {
                throw new ExcecaoConsultaMalsucedida();
            } else {
                return null;
            }

        } catch (Exception excecao) {
            throw new ExcecaoConsultaMalsucedida();
        }
    }

    @Override
    public List<Simulado> consultarSimulados(Date dataDeAtualizacao) throws ExcecaoConsultaMalsucedida {
        if (P.TEST) {
            return T.getMockListaDeSimulados();
        }

        StringBuilder url = new StringBuilder()
                .append("http://")
                .append(SERVER)
                .append("/edumobi/services/");

        try {
            String retorno = inputStreamToString(readJSON(url.toString()));

            if (retorno == null || retorno.isEmpty()) {
                throw new ExcecaoConsultaMalsucedida();
            } else {
                return null;
            }

        } catch (Exception excecao) {
            throw new ExcecaoConsultaMalsucedida();
        }
    }

    @Override
    public List<Questao> consultarQuestoesDoSimulado(Simulado simulado) throws ExcecaoConsultaMalsucedida {
        if (P.TEST) {
            return T.getMockListaDeQuestoesSimulado();
        }

        StringBuilder url = new StringBuilder()
                .append("http://")
                .append(SERVER)
                .append("/edumobi/services/");

        try {
            String retorno = inputStreamToString(readJSON(url.toString()));

            if (retorno == null || retorno.isEmpty()) {
                throw new ExcecaoConsultaMalsucedida();
            } else {
                return null;
            }

        } catch (Exception excecao) {
            throw new ExcecaoConsultaMalsucedida();
        }
    }
}